package com.bsi.core.fdfs;/*
 * Author: liusongs
 * Date: 2020/1/9 11:20
 * Content:
 */

import com.bsi.core.exception.BusinessException;
import com.bsi.core.utils.MathUtils;
import com.github.tobato.fastdfs.domain.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.util.Assert;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
@RefreshScope
public class DefaultFastDFSHandler implements FastDFSHandler {

    private static final Logger logger = LoggerFactory.getLogger(DefaultFastDFSHandler.class);

    @Value("${cbs.filePath_Windows}")
    private String filePathWin;

    @Value("${cbs.filePathOuter_Linux}")
    private String filePathLix;

    @Autowired
    private FastFileStorageClient fastFileStorageClient;

    @Autowired
    private FastDFSConfig fastDFSConfig;

    @Override
    public FastResultVo upload(File file) throws BusinessException, FileNotFoundException {
        Assert.notNull(file, "[DefaultFastDFSHandler->upload]->文件不能传入null值!");
        String ext = fastDFSConfig.isIgnore(file.getName());
        BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(file));
        StorePath storePath = fastFileStorageClient.uploadFile(fastDFSConfig.GROUP, inputStream, file.length(), ext);
        String accessUrl = fastDFSConfig.getNginxServer().endsWith("/") ? fastDFSConfig.getNginxServer() + storePath.getFullPath() : fastDFSConfig.getNginxServer() + "/" + storePath.getFullPath();
        return new FastResultVo(fastDFSConfig.GROUP, storePath.getFullPath(), accessUrl, file.length(), ext);
    }

    @Override
    public FastResultVo upload(MultipartFile file) throws IOException {
        Assert.notNull(file, "[DefaultFastDFSHandler->upload]->文件不能传入null值!");
        String ext = null;
        BufferedInputStream inputStream = null;
        StorePath storePath = null;
        String accessUrl = null;
        logger.info("==========>>附件开始上传==========>>");
        try {
            ext = fastDFSConfig.isIgnore(file.getOriginalFilename());
            inputStream = new BufferedInputStream(file.getInputStream());
            storePath = fastFileStorageClient.uploadFile(fastDFSConfig.GROUP, inputStream, file.getSize(), ext);
            accessUrl = fastDFSConfig.getNginxServer().endsWith("/") ? fastDFSConfig.getNginxServer() + storePath.getFullPath() : fastDFSConfig.getNginxServer() + "/" + storePath.getFullPath();
            logger.info("==========>>文件后缀："+ext+"||||"+"NginxServer："+fastDFSConfig.getNginxServer()+"||||"+"storePath："+storePath.getFullPath()+"||||"+"accessUrl："+accessUrl+"==========>>");
        } catch (BusinessException e) {
            logger.info("==========>>附件上传出错[BusinessException]==========>>");
            logger.error(e.getMessage());
        }catch (IOException e) {
            logger.info("==========>>附件上传出错[IOException]==========>>");
            logger.error(e.getMessage());
        }finally {
            inputStream.close();
        }
        logger.info("==========>>附件上传结束==========>>");
        return new FastResultVo(fastDFSConfig.GROUP, storePath.getFullPath(), accessUrl, file.getSize(), ext);
    }


    @Override
    public boolean delete(String groupPath) {
        try {
            fastFileStorageClient.deleteFile(fastDFSConfig.GROUP, groupPath);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    @Override
    public void printStream(HttpServletResponse response, String filename, String attUrl) throws IOException {
        InputStream inputStreamByUrl = DefaultFastDFSHandler.getInputStreamByUrl(attUrl);
        String encodedutf = new String(filename.getBytes(), "utf-8");
        String encodediso = new String(encodedutf.getBytes(), "iso-8859-1");
        response.addHeader("Content-Disposition", "attachment;filename=" + encodediso);
        ServletOutputStream outputStream = response.getOutputStream();
        FileCopyUtils.copy(inputStreamByUrl, outputStream);
    }

    /**
     * 传入输入流，返回输出流
     * @param response
     * @param filename
     * @param inputStream
     * @throws IOException
     */
    @Override
    public void printStream(HttpServletResponse response, String filename, InputStream inputStream) throws IOException {
        String encodedutf = new String(filename.getBytes(), "utf-8");
        String encodediso = new String(encodedutf.getBytes(), "iso-8859-1");
        response.addHeader("Content-Disposition", "attachment;filename=" + encodediso);
        ServletOutputStream outputStream = response.getOutputStream();
        FileCopyUtils.copy(inputStream, outputStream);
    }

    /**
     * 根据地址获得数据的输入流
     *
     * @param strUrl 网络连接地址
     * @return url的输入流
     */
    public static InputStream getInputStreamByUrl(String strUrl) {
        HttpURLConnection conn = null;
        try {
            URL url = new URL(strUrl);
            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(5 * 1000);
            final ByteArrayOutputStream output = new ByteArrayOutputStream();
            IOUtils.copy(conn.getInputStream(), output);
            return new ByteArrayInputStream(output.toByteArray());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (conn != null) {
                    conn.disconnect();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 附件上传服务器磁盘
     * @param file    文件
     * @param folder  文件目录(可传多个，动态创建)
     * @return
     * @throws IOException
     */
    public AttResultVo uploadFile(MultipartFile file, String[] folder) throws IOException {
        String fileName = file.getOriginalFilename();//原文件名
        String fileType = fileName.substring(fileName.lastIndexOf("."),fileName.length());
        String uuid = MathUtils.getUUId();
        String path = createMkdirs(folder);//创建文件目录，传入多个就创建多个目录，传入单个就创建单个目录
        File dest = new File(path+"/"+uuid+fileType);
        //判断文件父目录是否存在
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdir();
        }
        //上传
        file.transferTo(dest);
        return new AttResultVo(uuid,fileName,fileType,path,file.getSize());
    }

    /**
     * 动态创建文件目录
     * @param folder
     * @return
     */
    private String createMkdirs(String[] strs){
        String filePath = getSystemFilePath();
        if(strs.length == 0){
            return filePath;
        }
        for (String folder : strs) {
            filePath = filePath+folder+"/";
        }
        File file = new File(filePath);
        if(!file.exists()){
            file.mkdirs();
        }
        return file.getPath();
    }

    /**
     * 判断系统版本，文件保存路径 Windows和Linux配置不同路径
     * @return
     */
    public String getSystemFilePath(){
        String path="";
        String os = System.getProperty("os.name");
        if(os.toLowerCase().startsWith("win")){
            path = filePathWin;
        }else{
            path = filePathLix;
        }
        return path;
    }

}
